#include "stdafx.h"
#include "CppUnitTest.h"

#include <string>
#include <HSModel/Model3DStorage.h>
#include <HSModel/World.h>
#include <HSModel/WorldDumper.h>
#include <HSModel/Ground.h>
#include <HSModel/Human.h>
#include <HSModel/GameController.h>
#include <HSModel/BalloonsShop.h>
#include <HSModel/Bench.h>
#include <HSModel/World.h>
#include <HSModel/Water.h>
#include <HSModel/SharedConstants.h>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace HSModelTests
  {
  TEST_CLASS(WorldDumperTests)
    {
    public:
     
      class DerivedGameController : public GameController
        {
        public:
          size_t GetWaterCount()
            {
            return this->m_water_count;
            }
        };

      TEST_METHOD(GroundTypesAreProperlySavedAndRestored)
        {
        World world;
        world.GetGround()->SetGroundType(0, 0, GT_WALKWAY);
        world.GetGround()->SetGroundType(2, 1, GT_WALKWAY);

        GameController game_ctrl;
        WorldDumper dumper(world, game_ctrl, "DumperTests.xml");
        dumper.Dump();

        world.GetGround()->SetGroundType(0, 0, GT_GRASS);
        world.GetGround()->SetGroundType(2, 1, GT_GRASS);

        dumper.Restore();

        Assert::AreEqual((int) GT_WALKWAY, (int) world.GetGround()->GetGroundType(0, 0));
        Assert::AreEqual((int) GT_WALKWAY, (int) world.GetGround()->GetGroundType(2, 1));
        }

      TEST_METHOD(HumansAreProperlySavedAndRestored)
        {
        World world;
        world.AddHuman(TVector3(0, 1, 2));

        GameController game_ctrl;
        WorldDumper dumper(world, game_ctrl, "DumperTests.xml");
        dumper.Dump();

        World world2;
        WorldDumper dumper2(world2, game_ctrl, "DumperTests.xml");
        dumper2.Restore();

        Assert::AreEqual(size_t(1), world2.GetItems<Human>().size());
        Assert::AreEqual(2.0, world2.GetItems<Human>()[0]->GetPosition().Z());
        }

      TEST_METHOD(BenchesAreProperlySavedAndRestored)
        {
        World world;

        world.GetGround()->CreateWalkway(TVector2(3, 2));
        world.AddBench(TVector2(40, 20));
        world.AddBench(TVector2(30, 10));

        GameController game_ctrl;
        WorldDumper dumper(world, game_ctrl, "DumperTests.xml");
        dumper.Dump();

        World world2;
        WorldDumper dumper2(world2, game_ctrl, "DumperTests.xml");
        dumper2.Restore();

        Assert::AreEqual(size_t(2), world2.GetItems<Bench>().size());
        Assert::AreEqual(40.0,  world2.GetItems<Bench>()[0]->GetPosition().X());
        Assert::AreEqual(10.0,  world2.GetItems<Bench>()[1]->GetPosition().Y());
        }
      TEST_METHOD(BalloonsShopsAreProperlySavedAndRestored)
        {
        World world;
        world.AddBalloonsShop(TVector3(0, 1, 2));

        GameController game_ctrl;
        WorldDumper dumper(world, game_ctrl, "DumperTests.xml");
        dumper.Dump();

        World world2;
        WorldDumper dumper2(world2, game_ctrl, "DumperTests.xml");
        dumper2.Restore();

        Assert::AreEqual(size_t(1), world2.GetItems<BalloonsShop>().size());
        Assert::AreEqual(2.0, world2.GetItems<BalloonsShop>()[0]->GetPosition().Z());
        }

      TEST_METHOD(GameControllerWaterCounterTest)
      {
      World world;

      // Add water to model
      std::vector<std::shared_ptr<Water>> water_objects = HeightMapUtils::GetWaterModels(world.GetGround()->GetHeightMap(), GroundConstants::WATER_LEVEL);
      Assert::IsTrue(water_objects.size() >= 3);
      
      for (size_t i = 0; i < 3; ++i)
        world.GetGround()->AddWaterModel(water_objects[i]);

      DerivedGameController game_ctrl;
      WorldDumper dumper(world, game_ctrl, "DumperTests.xml");
      dumper.Dump();

      World world2;
      WorldDumper dumper2(world2, game_ctrl, "DumperTests.xml");
      dumper2.Restore();

      size_t water_count_actual = 3;
      size_t counter = game_ctrl.GetWaterCount();
      Assert::AreEqual(counter, water_count_actual);
      }
    };
  }